<template>
  <el-form
    ref="filterBox"
    :size="defaultFormItemSize"
    :model="formData"
    :label-width="(form().labelWidth || 100) + 'px'"
    :label-position="form().labelPosition"
    :style="{ display: totalWidgetCount > 0 || hasSlot || isEdit ? 'block' : 'none' }"
    @submit.prevent
  >
    <el-row
      class="online-filter-box"
      v-if="totalWidgetCount > 0 || hasSlot || isEdit"
      :style="{
        border: isEdit && !isAdvance ? '1px solid #e8eaec' : 'none',
        'min-height': isEdit && widgetList.length <= 0 ? '86px' : '0px',
      }"
    >
      <el-row
        v-draggable="[
          showWidgetList,
          {
            group: 'componentsGroup',
            disabled: !isEdit,
            draggable: '.custom-widget-item',
            group: 'componentsGroup',
            filter: '.filter',
          },
        ]"
        class="custom-widget-item"
        style="width: 100%; position: relative"
      >
        <slot class="filter" />
        <el-col
          v-for="(widget, index) in showWidgetList"
          :key="widget.variableName"
          :span="columnSpan"
          :style="getItemStyle(index, widget)"
          :class="{ active: isEdit && form().isActive(widget) }"
          class="custom-widget-item widget-item"
        >
          <el-form-item :prop="widget.propString" @click.stop="onWidgetClick(widget)">
            <template v-slot:label>
              <div>
                <span>{{ widget.showName }}</span>
                <ActiveWidgetMenu
                  v-if="isEdit && form().isActive(widget)"
                  :widget="widget"
                  @copy="onCopyWidget"
                  @delete="onDeleteWidget(widget)"
                />
              </div>
            </template>
            <OnlineCustomWidget
              :widget="widget"
              style="width: 100%"
              :ref="widget.variableName"
              :value="getWidgetValue(widget)"
              @input="val => onValueChange(widget, val)"
              @change="(val, dictData) => onWidgetValueChange(widget, val, dictData)"
            />
          </el-form-item>
        </el-col>
        <el-col :span="columnSpan" style="padding-left: 16px">
          <el-form-item label-width="0px">
            <el-button
              class="search-btn"
              :size="defaultFormItemSize"
              v-show="totalWidgetCount > 0"
              @click="onSearch"
              :icon="Search"
              >查询</el-button
            >
            <el-button
              :size="defaultFormItemSize"
              v-show="totalWidgetCount > 0"
              @click="onReset"
              style="width: 72px"
            >
              重置
            </el-button>
            <slot name="operator" />
            <el-row
              v-if="totalWidgetCount > props.rowCount - 1"
              type="flex"
              align="middle"
              class="expand-btn"
              @click="isExpand = !isExpand"
            >
              <span style="margin-right: 4px; font-size: 14px">
                {{ isExpand ? '收起' : '展开' }}
              </span>
              <el-icon :class="isExpand ? 'el-icon-arrow-up' : 'el-icon-arrow-down'">
                <ArrowUp v-if="isExpand" />
                <ArrowDown v-else />
              </el-icon>
            </el-row>
          </el-form-item>
        </el-col>
        <div
          v-if="isEdit && widgetList.length <= 0 && !hasSlot"
          class="info"
          :style="{ height: isAdvance ? '40px' : '60px' }"
        >
          <div>
            <el-icon><UploadFilled /></el-icon>
          </div>
          <span>请拖入组件进行编辑</span>
        </div>
      </el-row>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
import { FormInstance } from 'element-plus';
import { Search, UploadFilled, ArrowUp, ArrowDown } from '@element-plus/icons-vue';
import { useLayoutStore } from '@/store';
import { vDraggable } from 'vue-draggable-plus';
import OnlineCustomWidget from '@/online/components/OnlineCustomWidget.vue';
import ActiveWidgetMenu from '@/online/components/ActiveWidgetMenu.vue';
import { ANY_OBJECT } from '@/types/generic';

const emit = defineEmits(['copy', 'delete', 'search', 'reset', 'widgetClick']);
const props = defineProps({
  formData: {
    type: Object,
    required: true,
  },
  isEdit: {
    type: Boolean,
    default: false,
  },
  isAdvance: {
    type: Boolean,
    default: false,
  },
  isActive: {
    type: Boolean,
    default: false,
  },
  hasSlot: {
    type: Boolean,
    default: false,
  },
  widgetList: {
    type: Array,
    default: () => [],
  },
  rowCount: {
    type: Number,
    default: 4,
    validator: value => [1, 2, 3, 4, 6].includes(value),
  },
});
const layoutStore = useLayoutStore();
const form = inject('form', () => {
  return { isEdit: false } as ANY_OBJECT;
});

const widgetRefs: ANY_OBJECT = {};
const setWidgetRef = (el: Element | ComponentPublicInstance | null, name: string) => {
  if (el) {
    if (!widgetRefs[name]) {
      widgetRefs[name] = [];
    }
    widgetRefs[name].push(el);
  }
};

const isExpand = ref(false);
const filterBox = ref<FormInstance>();

const defaultFormItemSize = computed(() => {
  return layoutStore.defaultFormItemSize;
});

// Calculate column span based on rowCount
const columnSpan = computed(() => {
  // Element Plus uses a 24-column grid system
  return 24 / props.rowCount;
});

const defaultSlotCount = computed(() => {
  const instance = getCurrentInstance();
  if (!instance) return 0;
  const slots = instance.slots;
  if (!slots || !slots.default) return 0;
  return Array.isArray(slots.default()) ? slots.default().length : 0;
});

const totalWidgetCount = computed(() => {
  return (props.widgetList || []).length + defaultSlotCount.value;
});

const showWidgetList = computed(() => {
  // 如果isEdit和isExpand为true，则显示所有组件，否则只显示前 rowCount 个组件
  if (props.isEdit || isExpand.value) {
    return props.widgetList;
  } else {
    let count = props.rowCount - 1 - defaultSlotCount.value;
    let temp = count > 0 ? props.widgetList.slice(0, count) : [];
    return temp;
  }
});

const onCopyWidget = widget => {
  emit('copy', widget);
};

const onDeleteWidget = widget => {
  emit('delete', widget);
};

const getWidgetValue = widget => {
  if (props.isEdit) return;
  return form().getWidgetValue(widget);
};

const onValueChange = (widget, value) => {
  if (props.isEdit) return;
  return form().onValueChange(widget, value);
};

const onWidgetValueChange = (widget, value, dictData) => {
  if (props.isEdit) return;
  return form().onWidgetValueChange(widget, value, dictData);
};

const onWidgetClick = widget => {
  emit('widgetClick', widget);
};

const getItemStyle = (index, widget) => {
  return {
    display: form().getWidgetVisible(widget) ? 'block' : 'none',
  };
};

const onSearch = () => {
  emit('search');
};

const onReset = () => {
  emit('reset');
};

const resetWidget = (widget: ANY_OBJECT) => {
  if (widgetRefs[widget.variableName]) {
    widgetRefs[widget.variableName].forEach((ref: ANY_OBJECT) => {
      ref.reset();
    });
  }
};
</script>

<style scoped lang="scss">
.online-filter-box {
  background-color: white;
  padding: 16px 24px 0px 24px;
}
.online-filter-box .el-form-item {
  margin-bottom: 16px;
  width: 100%;
}
.info {
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 60px;
  text-align: center;
  color: #d9dbdd;
  vertical-align: middle;
}
.info div {
  width: 40px;
  height: 40px;
  font-size: 24px;
  text-align: center;
  border: 1px dashed #d9dbdd;
  border-radius: 6px;
  line-height: 40px;
}
.info span {
  margin-left: 10px;
  font-size: 16px;
}
.search-btn {
  color: $color-primary;
  border-color: $color-primary;
  &:hover {
    background-color: $color-primary-light-9;
  }
}
.expand-btn {
  margin-left: 20px;
  font-size: 16px;
  color: $color-primary;
  cursor: pointer;
}
</style>
